package com.bootdo.common.utils.orm;

import com.bootdo.common.utils.StringUtils;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
import java.util.Map;

/**
 * User: Allard
 * Date: 2017/6/27
 * Time: 15:32
 * Email: allards@synnex.com
 */
public abstract class HelpDaoImpl {
    protected EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public void setEntityManager(EntityManager entityManager){
        this.entityManager=entityManager;
    };

    /**
     * query list By Hql and '?' parameter if page are null will return all
     *
     * @param hql
     * @param parameters
     * @return
     */
    public <T> List<T> queryHQL(String hql, CommonPage<T> page, Object... parameters) {

        Query query = entityManager.createQuery(hql);
        if (null != page) {
            query.setFirstResult((page.getPageNumber() - 1) * page.getPageSize());
            query.setMaxResults(page.getPageSize());
            page.setTotalRows(0l);
        }

        if (null != page) {
            Long contentSize = this.countQueryHQL(hql, null, parameters);
            page.setTotalRows(contentSize);
        }


        if (parameters != null && parameters.length > 0) {
            Integer index = 1;
            for (int i = 0; i < parameters.length; i++) {
                Object obj = parameters[i];
                query.setParameter(index, obj);
                index++;
            }
        }
        List re = query.getResultList();
        if (null != page) {
            page.setData(re);
        }
        return re;
    }

    /**
     * if pagination are null will return all
     *
     * @param hql
     * @param parameters
     * @return
     */
    public <T> List<T> queryNamedHQL(String hql, CommonPage page, Map<String, Object> parameters) {
        Query query = entityManager.createQuery(hql);
        if (null != page) {
            query.setFirstResult((page.getPageNumber() - 1) * page.getPageSize());
            query.setMaxResults(page.getPageSize());
            page.setTotalRows(0l);
        }
        if (null != page) {
            Long contentSize = this.countQueryHQL(hql, parameters, null);
            page.setTotalRows(contentSize);
        }
        if (parameters != null) {
            for (String key : parameters.keySet()) {
                Object obj = parameters.get(key);
                query.setParameter(key, obj);
            }
        }

        List re = query.getResultList();
        if (null != page) {
            page.setData(re);
        }
        return re;
    }

    /**
     * @param sql
     * @param clazz
     * @param parameters
     * @return
     * @throws Exception
     */
    public <T> List<T> queryBySQL(String sql, Class<T> clazz, CommonPage page, Object... parameters) {
        Query query = entityManager.createNativeQuery(sql);
        if (null != page) {
            query.setFirstResult((page.getPageNumber() - 1) * page.getPageSize());
            query.setMaxResults(page.getPageSize());
            page.setTotalRows(0l);
        }
        if (null != page) {
            Long contentSize = this.countQuerySQl(sql, parameters);
            page.setTotalRows(contentSize);
        }

        if (null != parameters && parameters.length > 0) {
            int index = 1;
            for (int i = 0; i < parameters.length; i++) {
                Object obj = parameters[i];
                query.setParameter(index, obj);
                index++;
            }
        }
        query.unwrap(SQLQuery.class).setResultTransformer(Transformers.aliasToBean(clazz));
        List re = query.getResultList();
        if (null != page) {
            page.setData(re);
        }
        return re;
    }


    public int executeSqlUpdate(String sql, Object... values) {
        Query query = entityManager.createNativeQuery(sql);
        if (values != null) {
            for (int i = 0; i < values.length; i++) {
                query.setParameter(i, values[i]);
            }
        }
        return query.executeUpdate();
    }

    public int executeHqlUpdate(String hql, Object... values) {
        Query query = entityManager.createQuery(hql);
        if (values != null) {
            for (int i = 0; i < values.length; i++) {
                query.setParameter(i + 1, values[i]);
            }
        }
        return query.executeUpdate();

    }

    public int executeNameHqlUpdate(String hql, Map<String, Object> params) {
        Query query = entityManager.createQuery(hql);
        if (params != null) {
            for (String key : params.keySet()) {
                Object obj = params.get(key);
                query.setParameter(key, obj);
            }
        }
        return query.executeUpdate();
    }


    /**
     * the one of  mapparams and params must bo null
     *
     * @param mapparams
     * @param params
     * @return
     */
    public Long countQueryHQL(String sql, Map<String, Object> mapparams, Object... params) {
        Integer fistIndex = sql.toUpperCase().indexOf("FROM");
        Integer lastIndex = sql.toUpperCase().lastIndexOf("ORDER");
        String countHql = "";
        if (fistIndex > -1 && lastIndex > fistIndex) {
            countHql = " SELECT COUNT(*)  " + sql.substring(fistIndex, lastIndex);
        } else if (fistIndex > -1 && lastIndex < 0) {
            countHql = " SELECT COUNT(*)  " + sql.substring(fistIndex);
        }

        if (StringUtils.isEmpty(countHql)) {
            return 0l;
        }

        Query query = entityManager.createQuery(countHql);
        if (mapparams != null) {
            for (String key : mapparams.keySet()) {
                Object obj = mapparams.get(key);
                query.setParameter(key, obj);
            }
        } else if (params != null && params.length > 0) {
            Integer index = 1;
            for (int i = 0; i < params.length; i++) {
                Object obj = params[i];
                query.setParameter(index, obj);
                index++;
            }
        }
        Object o = query.getResultList().get(0);
        return o == null ? 0l : Long.valueOf(o.toString());
    }

    public Long countQuerySQl(String sql, Object... params) {
        Integer fistIndex = sql.toUpperCase().indexOf("FROM");
        Integer lastIndex = sql.toUpperCase().lastIndexOf("ORDER");
        String countsql = "";
        if (fistIndex > -1 && lastIndex > fistIndex) {
            countsql = " select count(*)  " + sql.substring(fistIndex, lastIndex);
        } else if (fistIndex > -1 && lastIndex < 0) {
            countsql = " select count(*)  " + sql.substring(fistIndex);
        }
        if (StringUtils.isEmpty(countsql)) {
            return 0l;
        }

        Query query = entityManager.createNativeQuery(countsql);
        if (null != params && params.length > 0) {
            int index = 1;
            for (int i = 0; i < params.length; i++) {
                Object obj = params[i];
                query.setParameter(index, obj);
                index++;
            }
        }
        Object o = query.getResultList().get(0);
        return o == null ? 0l : Long.valueOf(o.toString());
    }


}
